from Data.DataAPI.Landsat.request import API
from Data.DataAPI.Landsat.earthexplorer import EarthExplorer
from Data.DataStorage import *
from Util.Return import *
from Util.Process import *
from Util.SQL import *
import os
import tarfile
from PIL import Image


class LandsatAPI:
    def __init__(self):
        self.name = get_config("data", "Landsat")['name']
        self.username = get_config("config", "landsat_api_key")['username']
        self.password = get_config("config", "landsat_api_key")['password']
        self.download_path = get_path(os.path.abspath(__file__), 4, get_config("data", "Landsat")['download_path'])
        self.available_path = get_path(os.path.abspath(__file__), 4, get_config("data", "Landsat")['available_path'])
        self.quicklook_path = get_path(os.path.abspath(__file__), 4, get_config("data", "Landsat")['quicklook_path'])
        self.processingLevel = get_config("data", "Landsat")['processingLevel']
        self.datatype = get_config("data", "Landsat")['datatype']
        self.databand = get_config("data", "Landsat")['databand']
        self.max_cloud_cover = get_config("data", "Landsat")['max_cloud_cover']
        self.max_results = get_config("data", "Landsat")['max_results']

    def search(self, search_params):  # 通过API查询数据
        api = API(self.username, self.password)
        scenes = api.search(**search_params)
        INFO("INFO", f'Landsat API: Found {len(scenes)} scenes found')
        api.logout()
        return scenes

    def download(self, scenes):  # 通过API下载数据
        api = EarthExplorer(self.username, self.password)
        for scene_id in scenes:
            INFO("INFO", f'Landsat API: Start Download {scene_id}')
            try:
                api.download(scene_id, self.download_path)
            except Exception as e:
                INFO("ERROR", f'Landsat API: Download ERROR {scene_id}: {e}')
            INFO("INFO", f'Landsat API: Success Download {scene_id}')
        api.logout()

    def preprocess(self, scenes):  # 处理文件转为标准的TIFF和QUICKLOOK
        success = []
        for scene_id in scenes:
            INFO("INFO", f'Landsat API: Start Preprocess {scene_id}')
            tar_file = os.path.join(self.download_path, scene_id + '.tar')  # 压缩包路径
            if os.path.exists(tar_file):  # 判断是否存在
                with tarfile.open(tar_file, 'r') as tar:
                    for file in tar.getmembers():
                        if file.name.endswith(self.databand + '.TIF'):
                            tar.extract(file, self.available_path)  # 提取目标文件
                            os.rename(os.path.join(self.available_path, file.name),  # 重命名
                                      os.path.join(self.available_path, scene_id + '.TIFF'))
                        if file.name.endswith("thumb_large.jpeg"):
                            tar.extract(file, self.quicklook_path)  # 提取目标文件
                            os.rename(os.path.join(self.quicklook_path, file.name),  # 重命名
                                      os.path.join(self.quicklook_path, scene_id + '.png'))
                    tar.close()
                if not os.path.exists(os.path.join(self.quicklook_path, scene_id + '.png')):
                    image = Image.open(os.path.join(self.available_path, scene_id + '.TIFF'))
                    image = image.resize((1024, 1024))  # 调整图像大小为缩略图尺寸
                    image.save(os.path.join(self.quicklook_path, scene_id + '.png'), "PNG")  # 将图像保存为PNG格式
                success.append(True)
                INFO("INFO", f'Landsat API: Success Preprocess {scene_id}')
            else:
                INFO("ERROR", f'Landsat API: Preprocess ERROR {scene_id}')
                success.append(False)
        return success

    def upload(self, scenes):
        for scene_id in scenes:
            INFO("INFO", f"Landsat API: Start Upload {scene_id}")
            available_data = os.path.join(self.available_path, scene_id + ".TIFF")
            download_data = os.path.join(self.download_path, scene_id + ".tar")
            quicklook_data = os.path.join(self.quicklook_path, scene_id + ".png")
            local_data_list = [available_data, download_data, quicklook_data]
            hdfs_path_list = ["/" + get_config("data", "Landsat")['available_path'],
                              "/" + get_config("data", "Landsat")['download_path'],
                              "/" + get_config("data", "Landsat")['quicklook_path']]
            hdfs = HDFS()  # 创建一个HDFS连接
            Flag = True
            for index in range(len(local_data_list)):  # 上传
                hdfs.push(hdfs_path_list[index], local_data_list[index])
                if os.path.basename(local_data_list[index]) != scene_id + ".png":  # 不删除quicklook
                    os.remove(local_data_list[index])  # 删除文件
                    continue  # 处理特殊情况、不存在quick_look
                if not hdfs.exist(hdfs_path_list[index] + "/" + os.path.basename(local_data_list[index])):
                    Flag = False
            if Flag:
                update({"available": 1}, f'scene_id = "{scene_id}"', 'data')  # 更新数据为可用状态
                INFO("INFO", f"Landsat API: {scene_id} data is available!")
            else:
                INFO("INFO", f"Landsat API: {scene_id} data is not available!")

    def request(self, date, bbox=None, point=None):  # 请求且更新数据 bbox是一个元组
        datasets = self.processingLevel
        result_list = []
        for dataset in datasets:
            if point is None:
                search_params = {
                    'dataset': dataset,
                    'bbox': bbox,
                    'start_date': date[0],
                    'end_date': date[1],
                    'max_cloud_cover': self.max_cloud_cover,
                    'max_results': self.max_results
                }
            else:
                search_params = {
                    'dataset': dataset,
                    "longitude": point['lng'],
                    "latitude": point['lat'],
                    'start_date': date[0],
                    'end_date': date[1],
                    'max_cloud_cover': self.max_cloud_cover,
                    'max_results': self.max_results
                }
            scenes = self.search(search_params)
            result_list = result_list + self.resolve(scenes)
        return result_list

    def resolve(self, json_list):  # 解析API返回的查询json返回为数据库内的格式
        # 对原始json序列进行处理
        result = []
        for json_data in json_list:
            json_data.pop('spatial_coverage', None)
            time_key = ['acquisition_date', 'date_product_generated', 'start_time', 'stop_time', 'publish_date']
            for key in time_key:
                json_data[key] = json_data[key].strftime('%Y-%m-%d %H:%M:%S')
            json_data.pop('temporal_coverage', None)
            #####################
            result_json = {
                'dataset': self.name,
                'scene_id': json_data['display_id'],
                'type': self.datatype,
                'product': json_data['data_type'],
                'satellite': 'Landsat ' + str(json_data['satellite']),
                'date': json_data['acquisition_date'][:10],
                'address': get_address([((json_data['corner_upper_left_longitude'] + json_data[
                    'corner_lower_right_longitude']) / 2, (json_data['corner_upper_left_latitude'] + json_data[
                    'corner_lower_right_latitude']) / 2),
                                        (json_data['corner_upper_left_longitude'],
                                         json_data['corner_upper_left_latitude']),
                                        (json_data['corner_upper_right_longitude'],
                                         json_data['corner_upper_right_latitude']),
                                        (json_data['corner_lower_left_longitude'],
                                         json_data['corner_lower_left_latitude']),
                                        (json_data['corner_lower_right_longitude'],
                                         json_data['corner_lower_right_latitude'])]),
                'bbox': json_data['spatial_bounds'],
                'cbox': ((json_data['corner_upper_left_longitude'], json_data['corner_upper_left_latitude']),
                         (json_data['corner_upper_right_longitude'], json_data['corner_upper_right_latitude']),
                         (json_data['corner_lower_left_longitude'], json_data['corner_lower_left_latitude']),
                         (json_data['corner_lower_right_longitude'], json_data['corner_lower_right_latitude'])),
                'available': 0,
                'json': json_data
            }
            result.append(result_json)
        return result
